/*
 * @Description:
 * @Version: 1.0
 * @Author: xueyuankui
 * @Date: 2022-08-18 09:56:14
 * @LastEditors: xueyuankui
 * @LastEditTime: 2022-08-18 10:38:17
 */

#include <iostream>
#include <vector>
#include <memory>
#include <functional>
using namespace std;

class Entity
{
    using add_cb_t = std::function<int(int, int)>;

public:
    Entity() {}
    Entity(int i)
    {
        id = i;
    }
    void subscribe(add_cb_t add)
    {
        _add = std::move(add);
    }
    int add(int a, int b)
    {
        std::cout << "Entity:" << id << std::endl;
        return _add(a, b);
    }
    int id;

private:
    add_cb_t _add{nullptr};
};

class Adder
{
public:
    Adder(int c)
    {
        cookie = c;
    }
    int add(int a, int b)
    {
        std::cout << "cookie:" << cookie << ";"
                  << "a+b=" << a << "+" << b << std::endl;
        return a + b;
    }
    int cookie;
};

class Number
{
public:
    Number(int aa, int bb)
    {
        a = aa;
        b = bb;
    }
    int a;
    int b;
};
/**
 * @brief 绑定lambda函数
 *
 */
Entity entity1;
void bind_add()
{
    entity1.subscribe([](int a, int b)
                      {
        std::cout << "a+b=" << a+b << std::endl;
        return a+b; });
}
void test01()
{
    bind_add();
    entity1.add(10, 20);
}

/**
 * @brief 绑定lambda函数
 *
 */
std::vector<Entity> entities1;
void bind_adds1()
{
    Entity entity1;
    entity1.subscribe([](int a, int b)
                      {
            std::cout << "entity "<< 1 << ";" << "a+b=" << a + b << std::endl;
            return a + b; });
    entities1.emplace_back(entity1);

    Entity entity2;
    entity2.subscribe([](int a, int b)
                      {
            std::cout << "entity "<< 2 << ";" << "a+b=" << a + b << std::endl;
            return a + b; });
    entities1.emplace_back(entity2);
}

/**
 * @brief 绑定类成员
 *
 */
std::vector<Entity> entities2;
std::vector<Adder> adders2;
std::vector<Number> numbers{Number{1, 2}, Number{3, 4}, Number{5, 6}};
void bind_adds2()
{
    for (int i = 0; i < 3; ++i)
    {
        Entity entity{i};
        Adder adder{i};
        // 使用emplace_back添加列表成员可以避免拷贝
        adders2.emplace_back(adder);
        auto &number = numbers[i];
        //
        // entity.subscribe(std::bind(&Adder::add, adder, number.a, number.b)); // 错误， 绑定的对象不能使用局部变量（因为局部变量会被销毁）
        entity.subscribe(std::bind(&Adder::add, &adders2.back(), number.a, number.b)); // 正确
        entities2.emplace_back(entity);
    }
}

/**
 * @brief 绑定类成员
 *
 */
std::vector<Entity> entities3;
std::vector<Adder> adders3;
std::vector<Number> numbers{Number{1, 2}, Number{3, 4}, Number{5, 6}};
void bind_adds3()
{
    for (int i = 0; i < 3; ++i)
    {
        Entity entity{i};
        Adder adder{i};
        // 使用emplace_back添加列表成员可以避免拷贝
        adders3.emplace_back(adder);
        auto &number = numbers[i];

        // entity.subscribe([&number, &adders3.back()](int a, int b)
        //                  {
        //     adders3});
        entities3.emplace_back(entity);
    }
}

/**
 * @brief 列表成员改为指针
 *
 */
std::vector<std::shared_ptr<Entity>> entities4;

void bind_adds4()
{
    int idx = 0;
    for (int i = 0; i < 3; ++i)
    {
        auto entity = std::make_shared<Entity>();
        // 这里传入局部变量idx是不正确的
        // lambda函数运行时，无法找到绑定时的局部变量（因为改变量已经被销毁）
        entity->subscribe([&idx](int a, int b)
                          {
            std::cout << "entity "<< idx << ";" << "a+b=" << a + b << std::endl;
            return a + b; });
        entities4.emplace_back(entity);
        idx++;
    }
}

/**
 * @brief
 *
 */
void test02()
{
    bind_adds2();
    for (auto entity : entities2)
    {
        entity.add(10, 20);
    }

    // bind_adds3();
    // for (auto entity : entities3)
    // {
    //     entity->add(10, 20);
    // }
}
int main(int argc, char *argv[])
{
    // test01();
    test02();
    return 0;
}